package com.ht.managermentserver.config;

import com.ht.managermentserver.security.JwtAccessDeniedHandler;
import com.ht.managermentserver.security.JwtAuthenticationEntryPointEnd;
import com.ht.managermentserver.security.JwtAuthenticationTokenFilter;
import com.ht.managermentserver.security.JwtNameAndPasswordFilter;
import com.ht.managermentserver.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 跨域配置
 *
 * @author czy
 */
@Configuration
@EnableWebSecurity
@Order(-1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired SysUserService sysUserService;

  @Override
  protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(sysUserService).passwordEncoder(emptyPasswordEncoder());
  }

  public PasswordEncoder emptyPasswordEncoder() {
    return new PasswordEncoder() {
      @Override
      public String encode(final CharSequence rawPassword) {
        return rawPassword.toString();
      }

      @Override
      public boolean matches(final CharSequence rawPassword, final String encodedPassword) {
        return true;
      }
    };
  }

  @Override
  protected void configure(final HttpSecurity http)
      throws Exception { // CorsUtils::isPreFlightRequest
    http.cors()
        .and()
        .anonymous()
        .disable()
        .csrf()
        .disable()
        .addFilterBefore(
            new JwtAuthenticationTokenFilter(authenticationManager(), sysUserService),
            BasicAuthenticationFilter.class)
        .addFilterBefore(
            new JwtNameAndPasswordFilter(authenticationManager()),
            UsernamePasswordAuthenticationFilter.class)
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .exceptionHandling()
        .accessDeniedHandler(new JwtAccessDeniedHandler())
        .authenticationEntryPoint(new JwtAuthenticationEntryPointEnd())
        .and()
        .authorizeRequests()
        .anyRequest()
        .authenticated();
    ;
  }

  /**
   * 资源过滤
   *
   * @param web
   * @throws Exception
   */
  @Override
  public void configure(final WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers(
            "/swagger-ui.html/**",
            "/swagger-resources/**",
            "/v2/**",
            "/webjars/**",
            "/ui/index.html/**",
            "/static/**",
            "/ui/static/**",
            "/favicon.ico",
            "/**",
            "/ui/**");
  }

  @Bean
  public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource =
        new UrlBasedCorsConfigurationSource();
    final CorsConfiguration corsConfiguration = new CorsConfiguration();
    /* 是否允许请求带有验证信息 */
    corsConfiguration.setAllowCredentials(true);
    /* 允许访问的客户端域名 */
    corsConfiguration.addAllowedOrigin("*");
    /* 允许服务端访问的客户端请求头 */
    corsConfiguration.addAllowedHeader("*");
    /* 允许访问的方法名,GET POST等 */
    corsConfiguration.addAllowedMethod("*");
    urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsFilter(urlBasedCorsConfigurationSource);
  }
}
